package com.yds.dccjll.lib.base.util;

import android.text.TextUtils;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class BeanUtil {

    /**
     * 反射封装网络数据包
     * 目前只能封装一个json数组的字符串，json数组中的每个元素以T对象来封装，最后以列表返回
     * 如果jsonArrayString是空的，则返回一个只有一个空元素的列表；如果T对象的字节码为空，则返回一个将jsonArrayString作为唯一元素的列表
     * @param jsonArrayString   网络访问数据包
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> antiSerializationJsonString(String jsonArrayString, Class<T> clazz) {
        List dataList = new ArrayList();
        if(TextUtils.isEmpty(jsonArrayString) || "null".equalsIgnoreCase(jsonArrayString)){
//            dataList.add(null);
            return dataList;
        }
        try {
            if(clazz == null){
                dataList.add(jsonArrayString);
                return dataList;
            }
            JSONArray jsonArray = new JSONArray(jsonArrayString);
            for (int index=0;index<jsonArray.length();index++) {
                JSONObject jsonObject = jsonArray.getJSONObject(index);
                Object object = clazz.newInstance();
                Map<String, Class> fieldList = reflectClassFieldNameAndTypeMap(object);
                for (Map.Entry<String, Class> entry : fieldList.entrySet()) {
                    String fieldName = entry.getKey();
                    if (jsonObject.toString().contains("\"" + fieldName + "\"")) {
                        String firstChar = fieldName.substring(0, 1);
                        String methodName = "set" + fieldName.replaceFirst(firstChar, firstChar.toUpperCase(Locale.US));
                        Class[] methodParamType = getMethodParamTypes(clazz.newInstance(), methodName);
                        Method method = clazz.getDeclaredMethod(methodName, methodParamType);
                        try {
                            String fieldValue = jsonObject.getString(fieldName);
                            // && !"null".equalsIgnoreCase(fieldValue)
                            if(fieldValue != null){
                                method.invoke(object, fieldValue);
                            }
                        } catch (Exception e) {
                            //e.printStackTrace();
                            try {
                                method.invoke(object, jsonObject.getInt(fieldName));
                            } catch (Exception ignored) {
                                ignored.printStackTrace();
                            }
                        }
                    }
                }
                dataList.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return dataList;
    }

    private static Map<String, Class> reflectClassFieldNameAndTypeMap(Object obj) throws ClassNotFoundException {
        Map<String, Class> fieldMap = new HashMap<String, Class>();
        Class clazz;
        if (obj instanceof String) {
            String obj_string = (String) obj;
            clazz = Class.forName(obj_string);
        } else {
            clazz = obj.getClass();
        }
        Field[] fieldList = clazz.getDeclaredFields();
        for (Field field : fieldList) {
            fieldMap.put(field.getName(), field.getType());
        }
        return fieldMap;
    }

    @SuppressWarnings("rawtypes")
    private static Class[] getMethodParamTypes(Object classInstance, String methodName) throws ClassNotFoundException {
        Class[] paramTypes;
        paramTypes = null;
        Method[] methods = classInstance.getClass().getMethods();
        for (Method method : methods) {
            if (methodName.equals(method.getName())) {
                Class[] params = method.getParameterTypes();
                paramTypes = new Class[params.length];
                for (int j = 0; j < params.length; j++) {
                    String paramName = params[j].getName();
                    LogUtil.i("TAG", "paramName=" + paramName);
                    if ("int".equalsIgnoreCase(paramName)) {
                        paramName = "java.lang.Integer";
                    }
                    paramTypes[j] = Class.forName(paramName);
                }
                break;
            }
        }
        return paramTypes;
    }
}